﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using TAD;
using System.IO;

namespace MeuFreeCell
{
    public class Jogo: IDisposable
    {

        //variaveis locais
        public static int CartaHeight;
        public static int CartaWidth;
        private bool disposedValue;
        private ListaDinamica cartas;



        //Métodos externos utilizados pela aplicação para desenhar as cartas
        [DllImport("Cartas.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int cdtAnimate(IntPtr hDC, int ecbCartaBack, int x, int y, int iState);
        [DllImport("Cartas.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int cdtDraw(IntPtr hDC, int x, int y, int Carta, int Type, int clr);
        [DllImport("Cartas.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern bool cdtDrawExt(IntPtr hdc, int x, int y, int dx, int dy, int Carta, int type, long color);
        [DllImport("Cartas.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        private static extern bool cdtInit(ref int width, ref int height);
        [DllImport("Cartas.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]

        public static extern void cdtTerm();

        public void NovoJogo()
        {
 
        }

        public Naipe ValorDoNaipe(byte CartaValue)
        {
            switch (CartaValue)
            {
                case 0:
                case 4:
                case 8:
                case 12:
                case 16:
                case 20:
                case 24:
                case 28:
                case 32:
                case 36:
                case 40:
                case 44:
                case 48:
                    return Naipe.Paus;

                case 1:
                case 5:
                case 9:
                case 13:
                case 17:
                case 21:
                case 25:
                case 29:
                case 33:
                case 37:
                case 41:
                case 45:
                case 49:
                    return Naipe.Ouros;

                case 2:
                case 6:
                case 10:
                case 14:
                case 18:
                case 22:
                case 26:
                case 30:
                case 34:
                case 38:
                case 42:
                case 46:
                case 50:
                    return Naipe.Copas;
            }
            return Naipe.Espadas;
        }       

        public void ResetCartas(ref Carta[] todas)
        {
            todas = new Carta[] { 
        new Carta(0), new Carta(1), new Carta(2), new Carta(3), new Carta(4), new Carta(5), new Carta(6), new Carta(7), new Carta(8), new Carta(9), new Carta(10), new Carta(11), new Carta(12), new Carta(13), new Carta(14), new Carta(15), 
        new Carta(0x10), new Carta(0x11), new Carta(0x12), new Carta(0x13), new Carta(20), new Carta(0x15), new Carta(0x16), new Carta(0x17), new Carta(0x18), new Carta(0x19), new Carta(0x1a), new Carta(0x1b), new Carta(0x1c), new Carta(0x1d), new Carta(30), new Carta(0x1f), 
        new Carta(0x20), new Carta(0x21), new Carta(0x22), new Carta(0x23), new Carta(0x24), new Carta(0x25), new Carta(0x26), new Carta(0x27), new Carta(40), new Carta(0x29), new Carta(0x2a), new Carta(0x2b), new Carta(0x2c), new Carta(0x2d), new Carta(0x2e), new Carta(0x2f), 
        new Carta(0x30), new Carta(0x31), new Carta(50), new Carta(0x33)
            };
        }             

        private Face CardFaceValue(byte CardValue, Naipe suite)
        {
            return (Face)((byte)Math.Round((double)(((double)(CardValue - suite)) / 4.0)));
        }                      

        public Jogo(bool InitCards, ref Carta[] AllCards)
        {
            this.disposedValue = false;
            if (cdtInit(ref CartaWidth, ref CartaHeight))
            {
                if (InitCards)
                {
                    this.ResetCartas(ref AllCards);
                }
            }
            else
            {
                this.Dispose();
                EndApp();
            }
        }      

        public static void EndApp()
        {
            Environment.Exit(0);
        } 

        public void RandomGame(int number)
        {
            if (number > 0)
            {
                Random random = new Random(number);  
               // byte carta = random.Next(0,52)
            }
            else
            {
                throw new ArgumentException("O número deve ser maior que zero");
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);

        }

        public byte[] PrevOppositeSuite(byte CardValue)
        {
            Naipe s = this.ValorDoNaipe(CardValue);
            byte[] OppCards = new byte[2];
            Face f = this.CardFaceValue(CardValue, s);
            if (f == Face.Az)
            {
                f = Face.Reis;
            }
            else
            {
                f = (Face)((byte)(((int)f) - 1));
            }
            switch (((byte)s))
            {
                case 0:
                case 3:
                    //OppCards[0] = (byte)(((int)(f * Face.Cinco)) + 1); 

                    OppCards[0] = Convert.ToByte(((int)f * (int)Face.Cinco) + 1);

                    OppCards[1] = Convert.ToByte(((int)f * (int)Face.Cinco) + 2);
                    return OppCards;

                case 1:
                case 2:
                    OppCards[0] = Convert.ToByte(((int)f * (int)Face.Cinco) + 3);
                    OppCards[1] = Convert.ToByte(((int)f * (int)Face.Cinco) + 0);
                    return OppCards;
            }
            return OppCards;
        }             

        public byte[] NextOppositeSuite(byte CardValue)
        {
            Naipe s = this.ValorDoNaipe(CardValue);
            byte[] OppCards = new byte[2];
            Face f = this.CardFaceValue(CardValue, s);
            if (f == Face.Reis)
            {
                f = Face.Az;
            }
            else
            {
                f = (Face)((byte)(((int)f) + 1));
            }
            switch (((byte)s))
            {
                case 0:
                case 3:
                    OppCards[0] = Convert.ToByte(((int)f * (int)Face.Cinco) + 1);
                    OppCards[1] = Convert.ToByte(((int)f * (int)Face.Cinco) + 2);

                    return OppCards;

                case 1:
                case 2:
                    OppCards[0] = Convert.ToByte(((int)f * (int)Face.Cinco) + 3);
                    OppCards[1] = Convert.ToByte(((int)f * (int)Face.Cinco) + 0);
                    return OppCards;
            }
            return OppCards;
        }    

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                cdtTerm();
            }
            this.disposedValue = true;
        }   

        #endregion
    }
}
